"""
字段选择器对话框
用于从JSON结构中选择目标字段
"""
import tkinter as tk
from tkinter import ttk
from typing import Dict, Any, List, Optional


class FieldSelectorDialog:
    """字段选择器对话框"""

    def __init__(self, parent, json_config: Dict[str, Any], mode: str = 'single'):
        """
        Args:
            parent: 父窗口
            json_config: JSON配置对象
            mode: 选择模式，'single'=单选（返回list），'location'=经纬度模式（返回dict）
        """
        self.parent = parent
        self.json_config = json_config
        self.mode = mode
        self.result = None

        # 创建对话框
        self.dialog = tk.Toplevel(parent)
        self.dialog.title("选择目标字段")
        self.dialog.geometry("500x600")
        self.dialog.transient(parent)
        self.dialog.grab_set()

        # 居中显示
        self._center_dialog()

        self.setup_ui()

    def _center_dialog(self):
        """将对话框居中显示"""
        self.dialog.update_idletasks()
        width = self.dialog.winfo_width()
        height = self.dialog.winfo_height()
        x = (self.dialog.winfo_screenwidth() // 2) - (width // 2)
        y = (self.dialog.winfo_screenheight() // 2) - (height // 2)
        self.dialog.geometry(f'{width}x{height}+{x}+{y}')

    def setup_ui(self):
        """设置UI"""
        if self.mode == 'location':
            self._setup_location_ui()
        else:
            self._setup_tree_ui()

    def _setup_tree_ui(self):
        """设置树形选择器UI（单选/多选模式）"""
        # 提示标签
        ttk.Label(self.dialog, text="请从JSON结构中选择目标字段（支持多选）：").pack(anchor=tk.W, padx=10, pady=(10, 5))

        # 创建树形视图框架
        tree_frame = ttk.Frame(self.dialog)
        tree_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        # 创建树形视图
        self.tree = ttk.Treeview(tree_frame, selectmode='extended')
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

        # 添加滚动条
        scrollbar = ttk.Scrollbar(tree_frame, orient=tk.VERTICAL, command=self.tree.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.configure(yscrollcommand=scrollbar.set)

        # 已选字段显示区域
        selected_frame = ttk.LabelFrame(self.dialog, text="已选字段", padding=5)
        selected_frame.pack(fill=tk.BOTH, expand=False, padx=10, pady=5)

        self.selected_listbox = tk.Listbox(selected_frame, height=5)
        self.selected_listbox.pack(fill=tk.BOTH, expand=True)

        # 按钮区域
        button_frame = ttk.Frame(self.dialog)
        button_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Button(button_frame, text="添加选中", command=self.add_selected).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="移除", command=self.remove_selected).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="确定", command=self.confirm).pack(side=tk.RIGHT, padx=5)
        ttk.Button(button_frame, text="取消", command=self.cancel).pack(side=tk.RIGHT, padx=5)

        # 构建字段树
        self.build_field_tree()

    def _setup_location_ui(self):
        """设置经纬度选择器UI"""
        # 提示标签
        ttk.Label(self.dialog, text="请为经纬度模拟器选择目标字段：").pack(anchor=tk.W, padx=10, pady=(10, 5))

        # 纬度字段
        lat_frame = ttk.Frame(self.dialog)
        lat_frame.pack(fill=tk.X, padx=10, pady=5)
        ttk.Label(lat_frame, text="纬度字段:", width=12).pack(side=tk.LEFT)
        self.lat_var = tk.StringVar()
        self.lat_entry = ttk.Entry(lat_frame, textvariable=self.lat_var)
        self.lat_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        ttk.Button(lat_frame, text="选择...", command=lambda: self.select_for_location('lat')).pack(side=tk.LEFT)

        # 经度字段
        lng_frame = ttk.Frame(self.dialog)
        lng_frame.pack(fill=tk.X, padx=10, pady=5)
        ttk.Label(lng_frame, text="经度字段:", width=12).pack(side=tk.LEFT)
        self.lng_var = tk.StringVar()
        self.lng_entry = ttk.Entry(lng_frame, textvariable=self.lng_var)
        self.lng_entry.pack(side=tk.LEFT, fill=tk.X, expand=True, padx=5)
        ttk.Button(lng_frame, text="选择...", command=lambda: self.select_for_location('lng')).pack(side=tk.LEFT)

        # 字段树（用于选择）
        tree_label = ttk.Label(self.dialog, text="可用字段：")
        tree_label.pack(anchor=tk.W, padx=10, pady=(20, 5))

        tree_frame = ttk.Frame(self.dialog)
        tree_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

        self.tree = ttk.Treeview(tree_frame, selectmode='browse')
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        self.tree.bind('<Double-Button-1>', self.on_tree_double_click)

        scrollbar = ttk.Scrollbar(tree_frame, orient=tk.VERTICAL, command=self.tree.yview)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        self.tree.configure(yscrollcommand=scrollbar.set)

        # 按钮
        button_frame = ttk.Frame(self.dialog)
        button_frame.pack(fill=tk.X, padx=10, pady=10)

        ttk.Button(button_frame, text="确定", command=self.confirm).pack(side=tk.RIGHT, padx=5)
        ttk.Button(button_frame, text="取消", command=self.cancel).pack(side=tk.RIGHT, padx=5)

        # 构建字段树
        self.build_field_tree()

        # 当前待填充的字段类型
        self.current_location_field = None

    def build_field_tree(self):
        """构建字段树"""
        # 清空树
        for item in self.tree.get_children():
            self.tree.delete(item)

        # 配置文件的根级别就是body的定义，直接使用json_config
        if isinstance(self.json_config, dict):
            self._build_tree_recursive(self.json_config, '', None, 'body')

        # 展开所有节点
        self._expand_all_nodes()

    def _build_tree_recursive(self, node: Any, path_prefix: str, parent_item: Optional[str], node_name: str):
        """
        递归构建字段树

        Args:
            node: 当前节点
            path_prefix: 路径前缀
            parent_item: 父节点ID
            node_name: 当前节点名称
        """
        if isinstance(node, dict):
            # 判断节点类型
            node_type = node.get('type', '')
            node_display_name = node.get('name', node_name)

            # 构建当前路径
            if path_prefix:
                current_path = f"{path_prefix}.{node_display_name}"
            else:
                # 根节点：显示使用配置中的name，但路径强制使用'body'
                current_path = 'body'

            # 插入当前节点
            if node_type:
                # 有类型的节点（字段定义）
                display_text = f"{node_display_name} ({node_type})"
                item_id = self.tree.insert(parent_item or '', tk.END, text=display_text, values=(current_path,))
            else:
                # 容器节点
                display_text = node_display_name
                item_id = self.tree.insert(parent_item or '', tk.END, text=display_text, values=(current_path,))

            # 递归处理子节点
            if 'fields' in node and isinstance(node['fields'], list):
                # STRUCT的fields
                for field in node['fields']:
                    field_name = field.get('name', '')
                    if field_name:
                        self._build_tree_recursive(field, current_path, item_id, field_name)

            if 'entries' in node and isinstance(node['entries'], list):
                # MAP的entries
                parent_name = node.get('name', '')
                for entry in node['entries']:
                    key = entry.get('key', '')
                    entry_path = f"{current_path}.entries[{key}]"
                    entry_type = entry.get('type', '')

                    if entry_type == 'STRUCT' and 'fields' in entry:
                        # MAP中的STRUCT
                        entry_item = self.tree.insert(item_id, tk.END, text=f"entries[{key}]", values=(entry_path,))
                        for field in entry['fields']:
                            field_name = field.get('name', '')
                            if field_name:
                                self._build_tree_recursive(field, entry_path, entry_item, field_name)
                    else:
                        # MAP中的简单值
                        self.tree.insert(item_id, tk.END, text=f"entries[{key}] ({entry_type})", values=(entry_path,))

            if 'items' in node and isinstance(node['items'], dict):
                # ARRAY的items
                items = node['items']
                array_path = f"{current_path}.items[0]"
                items_type = items.get('type', '')

                if items_type == 'STRUCT' and 'fields' in items:
                    # ARRAY中的STRUCT
                    items_item = self.tree.insert(item_id, tk.END, text="items[0]", values=(array_path,))
                    for field in items['fields']:
                        field_name = field.get('name', '')
                        if field_name:
                            self._build_tree_recursive(field, array_path, items_item, field_name)
                else:
                    # ARRAY中的简单值
                    self.tree.insert(item_id, tk.END, text=f"items[0] ({items_type})", values=(array_path,))

    def _expand_all_nodes(self, parent=''):
        """递归展开所有树节点"""
        for item in self.tree.get_children(parent):
            self.tree.item(item, open=True)
            self._expand_all_nodes(item)

    def add_selected(self):
        """添加选中的字段到列表"""
        selected_items = self.tree.selection()
        for item in selected_items:
            values = self.tree.item(item, 'values')
            if values and len(values) > 0:
                field_path = values[0]
                # 检查是否已存在
                existing = self.selected_listbox.get(0, tk.END)
                if field_path not in existing:
                    self.selected_listbox.insert(tk.END, field_path)

    def remove_selected(self):
        """从列表中移除选中的字段"""
        selection = self.selected_listbox.curselection()
        if selection:
            self.selected_listbox.delete(selection[0])

    def select_for_location(self, field_type: str):
        """为经纬度模式选择字段"""
        self.current_location_field = field_type

    def on_tree_double_click(self, event):
        """双击树节点"""
        if self.mode == 'location' and self.current_location_field:
            # 获取选中的字段路径
            selected_items = self.tree.selection()
            if selected_items:
                item = selected_items[0]
                values = self.tree.item(item, 'values')
                if values and len(values) > 0:
                    field_path = values[0]
                    # 填充到对应的输入框
                    if self.current_location_field == 'lat':
                        self.lat_var.set(field_path)
                    elif self.current_location_field == 'lng':
                        self.lng_var.set(field_path)
                    self.current_location_field = None

    def confirm(self):
        """确认选择"""
        if self.mode == 'location':
            # 经纬度模式：返回dict
            lat = self.lat_var.get().strip()
            lng = self.lng_var.get().strip()
            if lat and lng:
                self.result = {'lat': lat, 'lng': lng}
                self.dialog.destroy()
            else:
                tk.messagebox.showwarning("提示", "请选择纬度和经度字段")
        else:
            # 单选/多选模式：返回list
            fields = list(self.selected_listbox.get(0, tk.END))
            if fields:
                self.result = fields
                self.dialog.destroy()
            else:
                tk.messagebox.showwarning("提示", "请至少选择一个字段")

    def cancel(self):
        """取消选择"""
        self.result = None
        self.dialog.destroy()

    def show(self) -> Optional[Any]:
        """显示对话框并返回结果"""
        self.dialog.wait_window()
        return self.result
